//---------------------------------------------------------------------------
// <copyright file="RibbonTextBox.cs" company="Microsoft Corporation">
//     Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
//---------------------------------------------------------------------------

namespace Microsoft.Windows.Controls.Ribbon
{
    #region Using declarations

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    
    #endregion

    /// <summary>
    ///   A TextBox which implements IRibbonControl so that it can be placed
    ///   in the Ribbon, and ICommandSource so that it can execute a RibbonCommand
    ///   upon pressing 'Enter'.
    /// </summary>
    public class RibbonTextBox : TextBox, IRibbonControl, ICommandSource
    {
        #region Constructors

        /// <summary>
        ///   Initializes static members of the RibbonTextBox class.  This also overrides
        ///   the default style, adds a coerce callback, and allows ToolTips to be shown
        ///   even when the control is disabled.
        /// </summary>
        static RibbonTextBox()
        {
            Type ownerType = typeof(RibbonTextBox);
            DefaultStyleKeyProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(ownerType));
            ToolTipProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceToolTip)));
            ToolTipService.ShowOnDisabledProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(true));
        }

        #endregion

        #region Public Properties

        /// <summary>
        ///   Gets or sets the Command that will be executed when the command source is invoked.
        /// </summary>
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        /// <summary>
        ///   Using a DependencyProperty as the backing store for CommandProperty.  This enables animation, styling, binding, etc...
        /// </summary>
        public static readonly DependencyProperty CommandProperty =
                    DependencyProperty.Register(
                            "Command",
                            typeof(ICommand),
                            typeof(RibbonTextBox),
                            new FrameworkPropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));

        /// <summary>
        ///   Gets or sets a user defined data value that can be passed to the command when it is executed.
        /// </summary>
        public object CommandParameter
        {
            get { return (object)GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        /// <summary>
        ///   Using a DependencyProperty as the backing store for CommandParameterProperty.  This enables animation, styling, binding, etc...
        /// </summary>
        public static readonly DependencyProperty CommandParameterProperty =
                    DependencyProperty.Register(
                            "CommandParameter",
                            typeof(object),
                            typeof(RibbonTextBox),
                            new FrameworkPropertyMetadata(null));

        /// <summary>
        ///   Gets or sets the object that the command is being executed on.
        /// </summary>
        public IInputElement CommandTarget
        {
            get { return (IInputElement)GetValue(CommandTargetProperty); }
            set { SetValue(CommandTargetProperty, value); }
        }

        /// <summary>
        ///   Using a DependencyProperty as the backing store for CommandTargetProperty.  This enables animation, styling, binding, etc...
        /// </summary>
        public static readonly DependencyProperty CommandTargetProperty =
                    DependencyProperty.Register(
                            "CommandTarget",
                            typeof(IInputElement),
                            typeof(RibbonTextBox),
                            new FrameworkPropertyMetadata(null));

        #endregion

        #region Public Methods

        /// <summary>
        ///   If the developer hasn't assigned their own tooltip, Create and attach a new RibbonToolTip.
        /// </summary>
        /// <param name="d">
        ///   The RibbonTextBox that the ToolTip property exists on.  When the callback is invoked,
        ///   the property system will pass this value.
        /// </param>
        /// <param name="value">The new value of the ToolTip property, prior to any coercion attempt.</param>
        /// <returns>The coerced value of the ToolTip property.</returns>
        public static object CoerceToolTip(DependencyObject d, object value)
        {
            if (value == null)
            {
                RibbonCommand command = ((RibbonTextBox)d).Command as RibbonCommand;
                if (command != null &&
                    (!string.IsNullOrEmpty(command.ToolTipTitle) || !string.IsNullOrEmpty(command.ToolTipDescription) || command.ToolTipImageSource != null))
                {
                    value = new RibbonToolTip(command);
                }
            }

            return value;
        }

        #endregion

        #region Protected Methods

        /// <summary>
        ///   Invoked each time a key-up event occurs.  When key-up occurs we
        ///   check to see if that key was 'Enter', and if so we invoke the
        ///   associated RibbonCommand.
        /// </summary>
        /// <param name="e">A KeyEventArgs that contains the event data.</param>
        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);

            if (e.Key == Key.Enter)
            {
                CommandHelpers.ExecuteCommandSource(null, this);
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        ///   If the Command property changes, we need to coerce some RibbonControl
        ///   specific properties to update their 'back-up' values coming from Command.
        /// </summary>
        /// <param name="d">The RibbonTextBox on which the Command property has changed value.</param>
        /// <param name="e">
        ///   Event data that is issued by any event that tracks changes to the effective value of this property.
        /// </param>
        private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RibbonTextBox textBox = (RibbonTextBox)d;
            textBox.CoerceValue(ToolTipProperty);
        }
        
        #endregion
    }
}